package com.xmindguoguo.boot.core.shiro.factroy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.xmindguoguo.boot.common.constant.GlobalConstant;
import com.xmindguoguo.boot.common.constant.factroy.ConstantFactory;
import com.xmindguoguo.boot.core.shiro.ShiroUser;
import com.xmindguoguo.boot.modular.system.model.TSystemRoleModel;
import com.xmindguoguo.boot.modular.system.model.TSystemUserModel;
import com.xmindguoguo.boot.modular.system.service.ITSystemMenuService;
import com.xmindguoguo.boot.modular.system.service.ITSystemRoleService;
import com.xmindguoguo.boot.modular.system.service.ITSystemUserService;
import com.xmindguoguo.boot.util.ConvertUtil;
import com.xmindguoguo.boot.util.spring.SpringContextHolder;

@Service
@DependsOn("springContextHolder")
@Transactional(readOnly = true)
public class ShiroFactroy implements IShiro {

    @Autowired
    public ITSystemUserService systemUserService;
    @Autowired
    private ITSystemMenuService systemMenuService;
    @Autowired
    public ITSystemRoleService systemRoleService;

    public static IShiro me() {
        return SpringContextHolder.getBean(IShiro.class);
    }

    /**
     * 获取用户model
     * 
     * @Title user
     * @author 于国帅
     * @date 2018年12月23日 下午3:01:05
     * @param account
     * @return
     * @see com.xmindguoguo.boot.core.shiro.factroy.IShiro#user(java.lang.String)
     */
    @Override
    public TSystemUserModel user(String account) {
        TSystemUserModel user = systemUserService.getByAccount(account);
        // 账号不存在
        if (null == user) {
            throw new UnknownAccountException();
        }
        // 账号被冻结 后面再开启
        if (user.getStatus() == GlobalConstant.USER_FREEZE) {
            throw new LockedAccountException();
        }
        return user;
    }

    /**
     * 获取 shiroUser 自定义Authentication对象
     * 
     * @Title shiroUser
     * @author 于国帅
     * @date 2018年12月23日 下午3:22:12
     * @param user
     * @return
     * @see com.xmindguoguo.boot.core.shiro.factroy.IShiro#shiroUser(com.xmindguoguo.boot.modular.system.model.TSystemUserModel)
     */
    @Override
    public ShiroUser shiroUser(TSystemUserModel user) {
        ShiroUser shiroUser = new ShiroUser();
        shiroUser.setId(user.getId()); // 账号id
        shiroUser.setAccount(user.getAccount());// 账号
        shiroUser.setDeptId(user.getDeptId()); // 部门id
        shiroUser.setDeptName(ConstantFactory.me().getDeptName(user.getDeptId()));// 部门名称
        shiroUser.setName(user.getName()); // 用户名称

        Long[] roleArray = ConvertUtil.StringToLongArray(user.getRoleId());// 角色集合
        List<Long> roleList = new ArrayList<>();
        List<String> roleNameList = new ArrayList<>();
        if (ArrayUtils.isNotEmpty(roleArray)) {
            for (Long roleId : roleArray) {
                roleList.add(roleId);
                roleNameList.add(ConstantFactory.me().getSingleRoleName(roleId));
            }
        }
        shiroUser.setRoleList(roleList);
        shiroUser.setRoleNames(roleNameList);

        return shiroUser;
    }

    /**
     * 获取权限列表
     * 
     * @Title findPermissionsByRoleId
     * @author 于国帅
     * @date 2018年12月23日 下午3:01:29
     * @param roleId
     * @return
     * @see com.xmindguoguo.boot.core.shiro.factroy.IShiro#findPermissionsByRoleId(java.lang.Integer)
     */
    @Override
    public List<String> findPermissionsByRoleId(Long roleId) {
        return systemMenuService.getResUrlsByRoleId(roleId);
    }

    /**
     * 获取角色Id
     * 
     * @Title findRoleNameByRoleId
     * @author 于国帅
     * @date 2018年12月23日 下午3:08:14
     * @param roleId
     * @return String
     */
    @Override
    public String findRoleNameByRoleId(Long roleId) {
        return ConstantFactory.me().getSingleRoleTip(roleId);
    }

    @Override
    public SimpleAuthenticationInfo info(ShiroUser shiroUser, TSystemUserModel user, String realmName) {
        String credentials = user.getPassword();
        // 密码加盐处理
        String source = user.getSalt();
        ByteSource credentialsSalt = new Md5Hash(source);
        return new SimpleAuthenticationInfo(shiroUser, credentials, credentialsSalt, realmName);
    }

    @Override
    public Set<String> findLoginNoPermissionSet() {
        return ConstantFactory.me().findLoginNoPermissionSet();
    }

    @Override
    public Set<String> findLoginAndPermissionSet() {
        return ConstantFactory.me().findLoginAndPermissionSet();
    }

    @Override
    public Set<String> findRoleNameSet() {
        Set<String> roleNameSet = new HashSet<>();
        Wrapper<TSystemRoleModel> wrapper = new EntityWrapper<>();
        List<TSystemRoleModel> roleList = systemRoleService.selectList(wrapper);
        if (CollectionUtils.isNotEmpty(roleList)) {
            for (TSystemRoleModel tSystemRoleModel : roleList) {
                roleNameSet.add(tSystemRoleModel.getName());
            }
        }
        return roleNameSet;
    }

    @Override
    public Set<String> findNoLoginAndPermissionSet() {
        return ConstantFactory.me().findNoLoginAndPermissionSet();
    }
}
